#include <opencv2/opencv.hpp>
#include <iostream>
#include <unistd.h>
#include <vector>
#include "CSerialPort/SerialPort.h"
#include "CSerialPort/SerialPortInfo.h"
#define imsleep(microsecond) usleep(1000 * microsecond) // ms

using namespace cv;
using namespace std;
using namespace itas109;
int main()
{
    // CSerialPort
    CSerialPort sp;
    std::vector<SerialPortInfo> m_availablePortsList = CSerialPortInfo::availablePortInfos();
    sp.init(m_availablePortsList[1].portName, // windows:COM1 Linux:/dev/ttyS0
            itas109::BaudRate115200,          // baudrate
            itas109::ParityNone,              // parity
            itas109::DataBits8,               // data bit
            itas109::StopOne,                 // stop bit
            itas109::FlowNone,                // flow
            4096                              // read buffer size
    );
    sp.open();
    char Buffer[1];
    // 打开摄像头
    VideoCapture cap(0);
    if (!cap.isOpened())
    {
        cout << "无法打开摄像头" << endl;
        return -1;
    }
    cap.set(cv::CAP_PROP_FRAME_WIDTH, 640);
    cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480);
    Mat frame, result, gray, edges, openedImage;
    cv::Mat kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(9, 9));

    std::vector<std::vector<cv::Point>> contours;
    std::vector<cv::Vec4i> hierarchy;
    // 存储检测到的矩形
    std::vector<cv::Rect> rectangles;
    int maxRectangles = 3;
    std::vector<Scalar> colors = {Scalar(0, 255, 0), Scalar(255, 0, 0), Scalar(0, 0, 255)}; // 定义三种颜色：绿色、蓝色、红色

    while (true)
    {
        // 读取当前帧
        cap >> frame;
        if (frame.empty())
        {
            break;
        }

        // 创建一个与原始帧大小相同的空白图像
        result = Mat::zeros(frame.size(), CV_8UC3);

        // 遍历图像的每个像素点
        for (int y = 0; y < frame.rows; y++)
        {
            for (int x = 0; x < frame.cols; x++)
            {
                // 获取当前像素点的RGB值
                Vec3b pixel = frame.at<Vec3b>(y, x);
                int b = pixel[0];
                int g = pixel[1];
                int r = pixel[2];

                // 计算RGB值的和
                int sum = r + g + b;

                // 如果RGB值的和大于600，则将该像素点标记为白色
                if ((sum < 170) && (sum) > 50)
                {
                    result.at<Vec3b>(y, x) = Vec3b(255, 255, 255);
                }
            }
        }

        // 形态学操作
        cv::morphologyEx(result, openedImage, cv::MORPH_CLOSE, kernel);

        // 转换为灰度图像
        cv::cvtColor(openedImage, gray, cv::COLOR_BGR2GRAY);

        // 高斯模糊
        cv::GaussianBlur(gray, gray, cv::Size(5, 5), 0);

        // 边缘检测
        cv::Canny(gray, edges, 50, 150);

        // 查找轮廓
        cv::findContours(edges, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);

        // 清空矩形存储
        rectangles.clear();

        // 遍历轮廓
        for (size_t i = 0; i < contours.size(); ++i)
        {
            // 近似轮廓
            std::vector<cv::Point> approx;
            cv::approxPolyDP(contours[i], approx, cv::arcLength(contours[i], true) * 0.02, true);

            // 如果是四边形且是凸的
            if (approx.size() == 4 && cv::isContourConvex(approx))
            {
                // 计算最小外接矩形
                cv::Rect rect = cv::boundingRect(approx);
                // 计算矩形区域的像素点数量
                Mat mask = Mat::zeros(gray.size(), CV_8UC1);
                drawContours(mask, contours, i, Scalar(255), FILLED);
                int pixelCount = countNonZero(mask(rect));

                // 如果像素点数量大于阈值，则认为是有效的矩形
                if (pixelCount > 1000)
                {
                    bool tooClose = false;
                    for (const auto &existingRect : rectangles)
                    {
                        // 检查新矩形是否与现有矩形太接近
                        if (abs(rect.x - existingRect.x) < 30 && abs(rect.y - existingRect.y) < 30)
                        {
                            tooClose = true;
                            break;
                        }
                    }
                    if (!tooClose)
                    {
                        std::cout << "pixel count " << pixelCount << std::endl;
                        rectangles.push_back(rect);
                    }
                }

                // 如果已经检测到足够多的矩形，则停止
                if (rectangles.size() >= maxRectangles)
                {
                    break;
                }
            }
        }

        // 遍历轮廓完成后，返回识别到的矩形像素点数量
        // size_t i = 0;
        // for (i; i < rectangles.size(); ++i)
        // {
        //     Mat mask = Mat::zeros(gray.size(), CV_8UC1);
        //     drawContours(mask, contours, i, Scalar(255), FILLED);
        //     int pixelCount = countNonZero(mask(rectangles[i]));
        //     // std::cout << "Rectangle " << rectangles.size() << " pixel count: " << pixelCount << std::endl;
        // }
        if (rectangles.size() != 0)
        {
            // std::cout << "Rectangle " << rectangles.size() << std::endl;
            // sprintf(Buffer, "%d", rectangles.size());
            std::size_t size = rectangles.size();
            // Buffer[0] = static_cast<char>(size);
            std::cout << "size:" << size << std::endl;
            // printf("Buffer:%c\r\n", Buffer[0]);
            sp.writeData(&size, sizeof(size));
        }
        for (size_t i = 0; i < rectangles.size(); ++i)
        {
            cv::rectangle(frame, rectangles[i], colors[i % colors.size()], 2);
        }

        // 显示原始帧和结果图像
        imshow("Original Frame", frame);
        imshow("Result Image", result);
        imshow("Opened Image", openedImage);
        imshow("gray Image", gray);
        // 按下ESC键退出循环
        if (waitKey(30) == 27)
        {
            break;
        }
    }

    // 释放摄像头并关闭窗口
    cap.release();
    destroyAllWindows();

    return 0;
}
